/*
 * Copyright 2011 SWM Services GmbH.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package de.swm.commons.mobile.client.presenter;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.HasWidgets;

import de.swm.commons.mobile.client.page.SimplePage;
import de.swm.commons.mobile.client.utils.Utils;
import de.swm.commons.mobile.client.widgets.page.IMainView;
import de.swm.commons.mobile.client.widgets.page.IPageWithHeader;
import de.swm.commons.mobile.client.widgets.page.IPageWithoutHeader;
import de.swm.gwt.client.eventbus.IDispatcher;
import de.swm.gwt.client.eventbus.IEvent;
import de.swm.gwt.client.mobile.Direction;
import de.swm.gwt.client.mobile.IPage;
import de.swm.gwt.client.mobile.ITransitionCompletedCallback;



/**
 * Abstract presenter class.
 * 
 */
public abstract class AbstractMobilePresenter {

	private final IDispatcher dispatcher;
	/** The global content area is null or contains a fixed toolbar on the button of the page. **/
	private static HasWidgets globalContentArea;
	private static Direction nextTransitionDirection = Direction.RIGHT;
	/** nur eine geichzeitige transition zulassen. **/
	private static boolean transitionIsRunning = false;
	private boolean isVisible = false;
	private ClickHandler backClickHandler = null;



	/**
	 * Default constructor.
	 * 
	 * @param disp
	 *            der dispatcher.
	 */
	public AbstractMobilePresenter(IDispatcher disp) {
		this.dispatcher = disp;
	}



	public IDispatcher getDispatcher() {
		return dispatcher;
	}



	/**
	 * Liefert die richtung der naechsten Transition. Dieses ist normalerweise recht. Falls ein Back-Navigatiosnevent
	 * vorgemerkt ist ist es ausnahmsweise rechts.
	 * 
	 * @return die Richtung des naechsten ueberganges.
	 */
	public static Direction getNextTransitionDirection() {
		if (!nextTransitionDirection.equals(Direction.RIGHT)) {
			Direction toReturn = nextTransitionDirection;
			nextTransitionDirection = Direction.RIGHT;
			return toReturn;
		}
		return nextTransitionDirection;
	}



	/**
	 * Created and adds a click handler for the back button. When the back button will be clicked the passed event will
	 * be fired (which should display the new page)
	 * 
	 * @param myView
	 *            currently displayed view.
	 * @param eventToFire
	 *            the event to fire after the back button will be clicked.
	 * @return the created internal click handler (e.g. to fire the event manually)
	 */
	protected ClickHandler addBackButtonNavigationHandlers(final IPageWithHeader myView, final IEvent eventToFire) {
		if (myView.getHeader() != null) {
			backClickHandler = new ClickHandler() {

				@Override
				public void onClick(ClickEvent event) {
					isVisible = false;
					nextTransitionDirection = Direction.LEFT;
					Utils.console("History Back Event >" + eventToFire.eventName());
					dispatcher.fireMobileEvent(eventToFire, myView.getView());
				}
			};
			myView.getHeader().setLeftButtonClickHandler(backClickHandler);
		}

		return backClickHandler;

	}



	/**
	 * Simulliert den click des Back buttons.
	 */
	public void goBack() {
		if (backClickHandler != null) {
			backClickHandler.onClick(null);
		}
	}



	/**
	 * Liefert rue wenn der vom Presenter kontollierte View sichtbar ist.
	 * 
	 * @return true wenn sichtbar.
	 */
	public boolean isOwningViewVisible() {
		return isVisible;
	}



	/**
	 * Generische trasitionsmethode fuer den Seitenwechsel.
	 * 
	 * @param newRootContentArea
	 *            new root content area. All new sceens will be places as chidlern of this area.
	 * @param startupCuntent
	 *            view which should be deplayed as content of the new root panel
	 */
	public void setRootContentArea(final IPage newRootContentArea, final IPageWithoutHeader startupCuntent) {
		// falls das Ursprungs-Panel das Main-View ist die content area wechseln
		if (globalContentArea == null && newRootContentArea != null && newRootContentArea instanceof IMainView) {
			globalContentArea = ((IMainView) newRootContentArea).toolbarPannel().getContentArea();
			globalContentArea.add(startupCuntent.getView().asComposite());
		}
	}



	/**
	 * Generische trasitionsmethode fuer den Seitenwechsel.
	 * 
	 * @param originator
	 *            der view der das Event ausgeloest hat
	 * @param targetView
	 *            die view des aktuellen Presenters (Ziel)
	 */
	public void gotoPage(final IPage originator, final IPageWithoutHeader targetView) {
		isVisible = true;
		setRootContentArea(originator, targetView);
		if (globalContentArea != null) {
			targetView.getView().setParent(globalContentArea);
			originator.setParent(globalContentArea);
		}

		// keine transition wenn Main-Wiew
		if (!transitionIsRunning && originator != null) {
			transitionIsRunning = true;
			originator.goTo(targetView.getView(), getNextTransitionDirection(), new ITransitionCompletedCallback() {
				@Override
				public void isCompleted() {
					Utils.console("Transition to Page (" + targetView.getView().getName() + ") completed");
					transitionIsRunning = false;
				}
			});
		} else if (!transitionIsRunning && originator == null) {
			// es gibt keinen originator
			Scheduler.get().scheduleDeferred(new ScheduledCommand() {
				@Override
				public void execute() {
					SimplePage.load(targetView.getView());
					transitionIsRunning = false;
				}
			});
			transitionIsRunning = true;
		}

	}

}
